#ifndef QUANTITY_H
#define QUANTITY_H
#include "LengthUnit.h"
#include "VolumeUnit.h"
#include <string>
#include <iostream>

template <class T>
class Quantity;

template <class T>
std::ostream& operator << (std::ostream& out, const Quantity <T>& quantity);

template <class T>
class Quantity{
  public:
    Quantity(unsigned int amount, const T &unit);
    Quantity(unsigned int amount, const T &unit, const T &formatUnit);
    bool operator == (const Quantity& quantity) const;
    Quantity operator + (const Quantity& quantity) const;

    friend std::ostream& operator << <>(std::ostream& out, const Quantity <T>& quantity);
    std::string toString() const;

  private:
    unsigned int m_amount;
    const T &m_unit;
    const T& m_formatUnit;
};

template <class T>
Quantity<T>::Quantity(unsigned int dimension, const T &unit)
  :m_amount(unit.convertToAmount(dimension)) 
  ,m_unit(unit)
  ,m_formatUnit(unit) {
}

template <class T>
Quantity<T>::Quantity(unsigned int dimension, const T &unit, const T &formatUnit)
  :m_amount(unit.convertToAmount(dimension)) 
  ,m_unit(unit)
  ,m_formatUnit(formatUnit) {
}

template <class T>
bool Quantity<T>::operator == (const Quantity<T>& quantity) const {
  return m_amount == quantity.m_amount;
}

template <class T>
Quantity<T> Quantity<T>::operator + (const Quantity<T>& quantity) const{
  return Quantity(m_amount + quantity.m_amount, (T&)this->m_unit.getBaseUnit());
}

template <class T>
std::string Quantity<T>::toString() const {
  return m_unit.toString(m_amount, m_formatUnit);
}

template <class T>
std::ostream& operator << (std::ostream& out, const Quantity <T>& quantity) {
  out << quantity.toString();
  return out;
}

#endif
